import SqlUtil from "../../Storage/SqlUtil";
import { ExtendsLoad } from "../CCExtends";
/**扩展原型组件 */
@ExtendsLoad(String)
export class StringBaseExtends {
    /**
    *  分割2个字符串检查字符串是否有重叠字符
    * @param name 节点名字
    * @param name2 子节点名字
    * @param chara 分割字符
    * @example
    *    String.checkHas("abc","cde") => true
    *    String.checkHas("abc","def") => false
    *    String.checkHas("a@b@c","c@d@e","@") => true
    */
    static checkHas(name: string, name2: string, chara = '') {
        if (name == null || name2 == null) return false;
        let str1 = name.trim().split(chara);
        let str2 = name2.trim().split(chara);
        for (let s of str1) {
            if (str2.includes(s))
                return true;
        }
        return false;
    }
    /**
     * 判断是否是空字符串
     * @returns boolen
     * @example
     *  String.isEmpty('ds') -> false
     */
    static isEmpty(str: string) {
        return str == null || str == "";
    }
}
/**扩展组件实例方法 */
@ExtendsLoad(String.prototype)
export class StringExtends {
    /**
     * 根据key保存指定值到内存中
     * @param saveStr 存储的key
     * @param elmName 值所在的key
     */
    static saveStr(saveStr: string, elmName: string) {
        let str = this as any as string;
        let isSave = SqlUtil.setItem(saveStr, str);
        if (isSave)
            SqlUtil._setOriginalName(saveStr + '_strElmName', elmName);
        else
            console.log(`存储OriginalName失败,key:${saveStr}`);
        return isSave;
    }

    /**
     * 从存储中加载指定数值到目标对象
     * @param target 要赋值的目标对象
     * @param saveStr 存储的key
     * @param def 默认值
     */
    static reloadStr(target: any, saveStr: string, def = 'defStr') {
        try {
            let name = SqlUtil._getOriginalName(saveStr + '_strElmName');
            if (name != null) {
                if (target && target[name] != null) {
                    target[name] = SqlUtil.getItem(saveStr, def);
                    return true;
                } else
                    console.warn(`要加载的数值目标不存在或者未创建`);
            } else
                console.warn(`要加载的数值目标 _strElmName 不存在`);
            return false;
        } catch (error) {
            return false;
        }
    }


    //#region  实用

    /**
    * 替换字符串中括号内的占位符号
    * @description 格式化字符串
    * @example
    * "{0}-->{1}-->{2}".format("one","two","three")  => "one-->two-->three"
    * "{0}-->{1}-->{2}".format(["one","two","three"])  => "one-->two-->three"
    */
    static format() {
        let sourceStr = this as any as string;
        let param = [];
        for (let i = 0, l = arguments.length; i < l; i++) {
            param.push(arguments[i]);
        }
        if (Array.isArray(param[0]) && param.length == 1) {
            param = param[0];
        }
        return sourceStr.replace(/\{(\d+)\}/g, function (m, n) {
            return param[n];
        });
    }

    /**
    * 分割2个字符串检查字符串是否有重叠字符
    * @param name2 子节点名字
    * @param chara 分割字符
    * @example
    * "abc".checkHas("cde") => true
    * "abc".checkHas("def") => false
    * "a@b@c".checkHas("c@d@e","@") => true
    */
    static checkHas(name2: string, chara = '') {
        let sourceStr = this as any as string;
        if (sourceStr == null || name2 == null) return false;
        let str1 = sourceStr.trim().split(chara);
        let str2 = name2.trim().split(chara);
        for (let s of str1) {
            if (str2.includes(s))
                return true;
        }
        return false;
    }

    /**
    * 在指定字符串中插入一段新的字符，并返回
    * @param soure 原始字符串
    * @param start 开始位置
    * @param insertStr 插入字符串的位置
    * @returns string
    * @example
    * '20217'.insertStr( 4, ".") => '2021.7'
    * '20217'.insertStr( 0, ".") => '.20217'
    */
    static insertStr(start: number, insertStr: string) {
        let sourceStr = this as any as string;
        return sourceStr.slice(0, start) + insertStr + sourceStr.slice(start);
    }

    /**
     * 转换文本中带有换行符号的
     * @param sourceStr 要转换的字符
     * @returns 换行后的字符
     * @example
     * 'abc\\nefg' => 'abc\nefg'
     */
    static transReturn() {
        let sourceStr = this as any as string;
        let _splitedStrings = sourceStr.split('\\n').map(str => str + '\n').join('').slice(0, -1); //删除最后一个换行符(长度为1)
        return _splitedStrings;
    }

    /**
     * 在指定字符中间隔指定长度插入新的字符
     * @param length 间隔index
     * @param insertStr 插入字符
     * @example
     * 'abcdefghi'.insertStrByCharator(4,'***') => 'abcd***efgh***i'
     */
    static insertStrByCharator(length: number, insertStr: string) {
        let sourceStr = this as any as string;
        return sourceStr.replace(new RegExp("(.{" + length + "})", "g"), "$1" + insertStr)
    }

    /**
     * 去除所有空客
     * @param value 
     * ‘abc def gh’.removeSpace() => ‘abcdefgh’
     */
    static removeSpace() {
        let sourceStr = this as any as string;
        return sourceStr.replace(/\s+/g, "");
    };

    //#endregion

    /**将 Base64 字符转为 cc.Texture2D 资源 */
    static base64ToTexture(): cc.Texture2D {
        let sourceStr = this as any as string;
        const image = document.createElement('img');
        image.src = sourceStr;
        const texture = new cc.Texture2D();
        texture.initWithElement(image);
        image.remove();
        return texture;
    }

    /**将 Base64 字符转为二进制数据 */
    static base64ToBlob(): Blob {
        let sourceStr = this as any as string;
        const strings = sourceStr.split(',');
        const type = /image\/\w+|;/.exec(strings[0])[0];
        const data = window.atob(strings[1]);
        const arrayBuffer = new ArrayBuffer(data.length);
        const uint8Array = new Uint8Array(arrayBuffer);
        for (let i = 0; i < data.length; i++) {
            uint8Array[i] = data.charCodeAt(i) & 0xff;
        }
        return new Blob([uint8Array], { type: type });
    }

    /**
    * Fisher–Yates shuffle 字符串随机乱序
    */
    static shuffleString(): string {
        let str = this as any as string;
        let arr: string[] = [];
        for (let i = 0; i < str.length; i++) {
            arr.push(str[i]);
        }
        arr = arr.fisherYatesShuffle();
        str = '';
        arr.forEach((v) => {
            str += v;
        });
        return str;
    }

    /**
    * 根据指定格式解析数值
    * @param value 值
    * @param delFormat 格式
    * @returns 数值
    * @example
    *  组件实际使用 后面跟数字表示限制参数
    *  {{0:sep}}将数字按分号显示   100000-> 100,000 
    *  {{0:per2}} 将取值0~1 变成 1~100,可以指定修饰的小数位数  
    *  {{0:int}} 将取值变成整数 
    *  {{0:fix2}}数值转换为小数
    *  {{0:kmbt2}}将数字缩短显示为KMBT单位 
    *  {{0:limit3}}字符串长度限制 
    *  使用{{1:int}} 表示替换组件绑定的路径中第一个的数据模型 并限制为int整数
    */
    static dealValue(delFormat: string): string {
        let value = this as any as number | string;
        if (delFormat === ``) return value as string;
        delFormat = delFormat.toLowerCase().trim();//不区分大小
        let match_func = delFormat.match(/^[a-z|A-Z]+/gi);//匹配到 format 中的 函数名
        let match_num = delFormat.match(/\d+$/gi);   //匹配到 format 中的参数
        let func = match_func ? match_func[0] : ``;
        let num = match_num ? parseInt(match_num[0]) : 0;
        let res: number | string = ``;

        /**
         * 压缩当前大数字
         * @param lang 语言
         * @param fixed 预留位数
         * @returns 
         */
        let converThousand = (value: number, lang: 'zh' | 'k' = 'k', fixed: number = 2) => {
            let units: [string[], number[]] = {
                'zh': [
                    ['', '千', '万', '亿', '兆', '京'],
                    [new Decimal('1000'), new Decimal('10000'), new Decimal('100000000'), new Decimal('1000000000000'), new Decimal('10000000000000000')]
                ],
                'k': [
                    ['', 'K', 'W', 'M', 'G', 'T'],
                    [new Decimal('1000'), new Decimal('10000'), new Decimal('1000000'), new Decimal('1000000000'), new Decimal('1000000000000')]
                ],
            }[lang] as any;
            let compressUnit = (v: number, count: number[], unit: string[], fixNum: number = 2) => {
                let res = v.toFixed(0);
                let index = 0;
                for (; index < count.length; index++) {
                    if (v < count[index]) {
                        if (index == 0)
                            res = v.toFixed(fixNum);
                        else
                            res = (v / count[index - 1]).toFixed(fixNum);
                        break;
                    }
                }
                return res + unit[index];
            }
            switch (lang) {
                case `zh`:
                    return compressUnit(value, units[1], units[0], fixed);
                case `k`:
                    return compressUnit(value, units[1], units[0], fixed);
                default:
                    break;
            }
        }

        if (typeof value.valueOf() == `number`) {
            let v = value.valueOf() as number;
            switch (func) {
                /** [value:int] 将取值变成整数 */
                case `int`: res = Math.round(v); break;
                /** [value:fix]数值转换为小数*/
                case `fix`: res = v.toFixed(num); break;
                /** [value:kmbt]将数字缩短显示为KMBT单位  */
                case `kmbt`: res = converThousand(v, 'k', num); break;
                /** [value:per] 将取值0~1 变成 1~100,可以指定修饰的小数位数 */
                case `per`: res = Math.round(v * 100).toFixed(num); break;
                /**[value:sep]将数字按分号显示 100000-> 100,000 */
                case `sep`: res = Math.round(v).toString().replace(new RegExp(`(\\d)(?=(\\d{ 3}) + $)`, `ig`), "$1,"); break;
                default: break;
            }
        } else {
            let s = value.valueOf() as string;
            switch (func) {
                /** [value:limit]字符串长度限制 */
                case `limit`: res = s.substring(0, num); break;
                default: break;
            }
            // res = value;
        }
        return res as string;
    }
}